package com.yingxin.yx.framework.commons.helper.loop;

import com.yingxin.yx.framework.commons.helper.DecimalHelper;
import com.yingxin.yx.framework.commons.helper.loop.setter.LoopBigDecimalAvgSetter;

import java.math.BigDecimal;
import java.util.List;
import java.util.function.Function;

public class LoopAvgHelper {


    /**
     * 加权平均
     * @param list          列表
     * @param totalVal      需要平均的值
     * @param totalWeighted 总权重的值 分母
     * @param getter        获取item的权重 分子
     * @param setter        返回 item itemVal itemPercent
     * @param <T>
     */
    public static <T> void decimalAvg(List<T> list, BigDecimal totalVal, BigDecimal totalWeighted,
                                      Function<T, BigDecimal> getter, LoopBigDecimalAvgSetter<T> setter) {
        int idx = 0;
        // 已经分摊的电费总数
        BigDecimal sumVal = BigDecimal.ZERO;
        // 已经分摊的百分比
        BigDecimal sumPercent = BigDecimal.ZERO;
        for (T t : list) {
            BigDecimal itemVal;
            BigDecimal itemPercent;
            if (idx == list.size() - 1) {
                itemVal = DecimalHelper.subtract(totalVal, sumVal);
                itemPercent = DecimalHelper.subtract(BigDecimal.ONE, sumPercent);
            } else {
                BigDecimal weighted = (getter.apply(t) == null ? BigDecimal.ZERO : getter.apply(t));
                itemPercent = DecimalHelper.divide(weighted, totalWeighted);
                itemVal = DecimalHelper.multiply(itemPercent, totalVal);
                sumVal = DecimalHelper.add(sumVal, itemVal);
                sumPercent = DecimalHelper.add(sumPercent, itemPercent);
            }
            idx++;
            setter.apply(t, itemVal, itemPercent);
        }
    }

    /**
     * 加权平均
     * @param list          列表
     * @param totalVal      需要平均的值
     * @param totalWeighted 总权重的值 分母
     * @param getter        获取item的权重 分子
     * @param setter        返回 item itemVal itemPercent
     * @param <T>
     */
    public static <T> void decimalAvg2(List<T> list, BigDecimal totalVal, BigDecimal totalWeighted, Function<T, BigDecimal> getter, LoopBigDecimalAvgSetter<T> setter) {
        int idx = 0;
        BigDecimal sumVal = BigDecimal.ZERO;
        BigDecimal sumPercent = BigDecimal.ZERO;
        for (T t : list) {
            BigDecimal itemVal;
            BigDecimal itemPercent;
            if (idx == list.size() - 1) {
                itemVal = DecimalHelper.subtract(totalVal, sumVal);
                itemPercent = DecimalHelper.subtract(BigDecimal.ONE, sumPercent);
            } else {
                BigDecimal weighted = (getter.apply(t) == null ? BigDecimal.ZERO : getter.apply(t));
                itemPercent = DecimalHelper.divide(weighted, totalWeighted);
                itemVal = DecimalHelper.multiply(itemPercent, totalVal).setScale(2, BigDecimal.ROUND_HALF_DOWN);
                sumVal = DecimalHelper.add(sumVal, itemVal);
                sumPercent = DecimalHelper.add(sumPercent, itemPercent);
            }
            idx++;
            setter.apply(t, itemVal, itemPercent);
        }
    }

    /**
     * 加权平均
     * @param list          列表
     * @param totalVal      需要平均的值
     * @param totalWeighted 总权重的值 分母
     * @param getter        获取item的权重 分子
     * @param setter        返回 item itemVal itemPercent
     * @param <T>
     */
    public static <T> void amtDecimalAvg(List<T> list, BigDecimal totalVal, BigDecimal totalWeighted, Function<T, BigDecimal> getter, LoopBigDecimalAvgSetter<T> setter) {
        int idx = 0;
        BigDecimal sumVal = BigDecimal.ZERO;
        BigDecimal sumPercent = BigDecimal.ZERO;
        for (T t : list) {
            BigDecimal itemVal;
            BigDecimal itemPercent;
            if (idx == list.size() - 1) {
                itemVal = DecimalHelper.subtract(totalVal, sumVal);
                itemPercent = DecimalHelper.subtract(BigDecimal.ONE, sumPercent);
            } else {
                BigDecimal weighted = (getter.apply(t) == null ? BigDecimal.ZERO : getter.apply(t));
                itemPercent = DecimalHelper.divide(weighted, totalWeighted, 4);
                itemVal = DecimalHelper.multiply(itemPercent, totalVal, 2);
                sumVal = DecimalHelper.add(sumVal, itemVal);
                sumPercent = DecimalHelper.add(sumPercent, itemPercent);
            }
            idx++;
            setter.apply(t, itemVal, itemPercent);
        }
    }

}
